package cn.stylefeng.guns.modular.business.frequency.finance.controller;

import cn.stylefeng.guns.core.annotion.BusinessLog;
import cn.stylefeng.guns.core.context.login.LoginContextHolder;
import cn.stylefeng.guns.core.enums.LogAnnotionOpTypeEnum;
import cn.stylefeng.guns.core.factory.PageFactory;
import cn.stylefeng.guns.core.pojo.page.PageResult;
import cn.stylefeng.guns.core.pojo.response.ResponseData;
import cn.stylefeng.guns.modular.business.custom.annotations.RepeatSubmit;
import cn.stylefeng.guns.modular.business.custom.enums.ReturnCode;
import cn.stylefeng.guns.modular.business.frequency.finance.model.param.FinanceCheckVO;
import cn.stylefeng.guns.modular.business.frequency.finance.model.param.FinanceDTO;
import cn.stylefeng.guns.modular.business.frequency.finance.model.param.SettlementVO;
import cn.stylefeng.guns.modular.business.frequency.finance.model.result.FinanceCheckSummaryVO;
import cn.stylefeng.guns.modular.business.frequency.finance.model.result.PkgFinanceCheck;
import cn.stylefeng.guns.modular.business.frequency.finance.model.result.PkgFinanceSettlement;
import cn.stylefeng.guns.modular.business.frequency.finance.model.result.TransportSettlementVO;
import cn.stylefeng.guns.modular.business.frequency.finance.service.FinanceService;
import cn.stylefeng.guns.modular.business.frequency.financecheck.entity.FinanceCheck;
import cn.stylefeng.guns.modular.business.frequency.financedetail.entity.FinanceDetail;
import cn.stylefeng.guns.modular.business.frequency.financesettlement.entity.FinanceSettlement;
import cn.stylefeng.guns.modular.business.frequency.financetransport.entity.FinanceTransport;
import cn.stylefeng.guns.modular.business.frequency.orderextrafee.entity.OrderExtraFee;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description:
 * @Author jzy
 * @Date 2020/11/10 0010
 **/
@Api(tags = "财务模块")
@RestController
@RequestMapping("/api/finance")
public class FinanceController {

    @Resource
    private FinanceService financeService;

    @ApiOperation(value = "应收列表")
    @GetMapping("/collection")
    public ResponseData getCollectionList(FinanceDTO financeDTO) {
        // 排序
        if (StringUtils.isBlank(financeDTO.getColumn())) {
            financeDTO.setColumn("f.create_time");
        }
        return financeService.getCollectionList(PageFactory.defaultPage(), financeDTO);
    }

    @ApiOperation(value = "网点待收列表")
    @GetMapping("/siteCollection")
    public ResponseData getSiteCollection() {
        return financeService.getSiteCollection(PageFactory.defaultPage());
    }

    @ApiOperation(value = "应付列表")
    @GetMapping("/payment")
    public ResponseData getPaymentList(FinanceDTO financeDTO) {
        // 排序
        if (StringUtils.isBlank(financeDTO.getColumn())) {
            financeDTO.setColumn("os.create_time");
        }
        return financeService.getPaymentList(PageFactory.defaultPage(), financeDTO);
    }


    @ApiOperation(value = "app网点应付列表")
    @GetMapping("/sitePayment")
    public ResponseData sitePayment() {
        return financeService.sitePayment();
    }

    @ApiOperation(value = "承运费应付列表")
    @GetMapping("/payment/transport/{orderId}")
    public ResponseData<List<FinanceTransport>> getPaymentTransportList(@PathVariable String orderId) {
        List<FinanceTransport> list = financeService.getPaymentTransportListByOrderId(orderId);
        return ResponseData.andaSuccess(list);
    }

    @ApiOperation(value = "其他费用应付列表")
    @GetMapping("/payment/extra/{orderId}")
    public ResponseData<List<OrderExtraFee>> getPaymentExtraList(@PathVariable String orderId) {
        List<OrderExtraFee> list = financeService.getPaymentExtraListByOrderId(orderId);
        return ResponseData.andaSuccess(list);
    }

    @ApiOperation(value = "对账单")
    @GetMapping("/check")
    public ResponseData getFinanceCheckList(FinanceDTO financeDTO) {
        if (financeDTO.getCheckTransportNoList().size() == 0
                && (financeDTO.getSettlementIdList() == null || financeDTO.getSettlementIdList().size() == 0)) {
            return ResponseData.andaError("请输入对账条件");
        }
        List<PkgFinanceCheck> list = financeService.getFinanceCheckList(financeDTO);
        FinanceCheckSummaryVO data = new FinanceCheckSummaryVO();
        data.setList(list);
        data.setSummary(financeService.getFinanceCheckSummary(financeDTO));
        return ResponseData.andaSuccess(data);
    }

    @ApiOperation(value = "获取对账单金额数据")
    @PostMapping("/getFinanceCheckSummary")
    public ResponseData getFinanceCheckSummary(@RequestBody FinanceDTO financeDTO) {
        FinanceCheckSummaryVO data = new FinanceCheckSummaryVO();
        data.setSummary(financeService.getFinanceCheckSummary(financeDTO));
        return ResponseData.andaSuccess(data);
    }

    @ApiOperation(value = "毛利表")
    @GetMapping("/gross")
    public ResponseData getFinanceGrossList(FinanceDTO financeDTO) {
        // 排序
        if (StringUtils.isBlank(financeDTO.getColumn())) {
            financeDTO.setColumn("orderId");
        }
        return financeService.getFinanceGrossList(PageFactory.defaultPage(), financeDTO);

    }

    @ApiOperation(value = "应收/应付结算")
    @PostMapping("/collection/settlement")
    @PreAuthorize("@el.check('finance:settlement')")
    @RepeatSubmit(expireSeconds = 3)
    public ResponseData collectionSettlement(@RequestBody SettlementVO settlementVO) {
        StringBuilder errorMsg = new StringBuilder();
        if (!financeService.checkSettlement(settlementVO, errorMsg)) {
            return ResponseData.andaError(errorMsg.toString());
        }
        settlementVO.setOperatorUser(LoginContextHolder.me().getSysLoginUserId());
        financeService.settlement(settlementVO);
        return ResponseData.andaSuccess();
    }

    @ApiOperation(value = "应收/应付结算审核")
    @PostMapping("/collection/settlementAudit")
    @PreAuthorize("@el.check('finance:settlement')")
    @RepeatSubmit(expireSeconds = 3)
    public ResponseData settlementAudit(@Validated @RequestBody SettlementVO settlementVO) {
       /* 逻辑修改,不需要审核,和上面接口保持一致
        StringBuilder errorMsg = new StringBuilder();
        if (!financeService.checkSettlement(settlementVO, errorMsg)) {
            return ResponseData.andaError(errorMsg.toString());
        }
        settlementVO.setOperatorUser(LoginContextHolder.me().getSysLoginUserId());
        financeService.settlement2(settlementVO);
        StringBuilder errorMsg = new StringBuilder();
        if (!financeService.checkSettlement(settlementVO, errorMsg)) {
            return ResponseData.andaError(errorMsg.toString());
        }*/
        StringBuilder errorMsg = new StringBuilder();
        if (!financeService.checkSettlement(settlementVO, errorMsg)) {
            return ResponseData.andaError(errorMsg.toString());
        }
        settlementVO.setOperatorUser(LoginContextHolder.me().getSysLoginUserId());
        financeService.settlement(settlementVO);
        return ResponseData.andaSuccess();
    }


    @ApiOperation(value = "承运费结算")
    @PostMapping("/transport/settlement")
    @PreAuthorize("@el.check('finance:settlement')")
    @RepeatSubmit(expireSeconds = 3)
    public ResponseData transportSettlement(@RequestBody TransportSettlementVO transportSettlementVO) {
        StringBuilder errorMsg = new StringBuilder();
        if (!financeService.checkTransportSettlement(transportSettlementVO, errorMsg)) {
            return ResponseData.andaError(errorMsg.toString());
        }
        financeService.transportSettlement(transportSettlementVO);
        return ResponseData.andaSuccess();
    }

    @ApiOperation(value = "其他费用结算")
    @PostMapping("/extra/settlement")
    @PreAuthorize("@el.check('finance:settlement')")
    @RepeatSubmit(expireSeconds = 3)
    public ResponseData extraSettlement(@RequestBody TransportSettlementVO transportSettlementVO) {
        StringBuilder errorMsg = new StringBuilder();
        if (!financeService.checkExtraSettlement(transportSettlementVO, errorMsg)) {
            return ResponseData.andaError(errorMsg.toString());
        }
        financeService.extraSettlement(transportSettlementVO);
        return ResponseData.andaSuccess();
    }

    @ApiOperation(value = "对账单结算")
    @PostMapping("/check/settlement")
    @PreAuthorize("@el.check('finance:settlement')")
    @RepeatSubmit(expireSeconds = 3)
    public ResponseData checkSettlement(@RequestBody FinanceCheckVO financeCheckVO) {
        FinanceDTO financeDTO = new FinanceDTO();

        // 结算人、运单号不可同时结算
        /*if (checkMultiCondition(financeCheckVO)) {
            return ResponseData.andaError("结算人、运单号不可同时搜索结算");
        }*/
        // -----end---
        if (financeCheckVO.getSettlementIdList() != null && financeCheckVO.getSettlementIdList().size() > 0) {
            List<String> siteAndSettlement = new ArrayList<>();
            List<String> transportList = new ArrayList<>();
            for (String id : financeCheckVO.getSettlementIdList()) {
                if (StringUtils.isBlank(id)) {
                    continue;
                }
                if (id.length() < 10) {
                    transportList.add(id);
                } else if (id.length() > 10) {
                    siteAndSettlement.add(id);
                }
            }
            financeDTO.setSettlementIdList(siteAndSettlement);
            financeDTO.setCheckTransportNoList(transportList);
        } else {
            return ResponseData.andaError("请至少选择一条数据进行结算！");
        }

        financeDTO.setOrderIdList(financeCheckVO.getOrderIdList());
        if (financeDTO.getCheckTransportNoList().size() > 0) {
            for (String transportNo : financeDTO.getCheckTransportNoList()) {
                String transportSettlementId = financeService.getSettlementIdByTransportNo(transportNo);
                if (StringUtils.isBlank(transportSettlementId)) {
                    return ResponseData.andaError("所选运单" + transportNo + "数据存在未处理的结算人，请联系管理员！");
                } else {
                    financeDTO.getSettlementIdList().add(transportSettlementId);
                }
            }

        }
        List<FinanceDetail> list = financeService.getCheckFinanceDetail(financeDTO);
        //List<PkgFinanceCheck> checkList = financeService.getFinanceCheckList(financeDTO);
        if (list != null && list.size() > 0) {
            // 对账单批量结算
            financeService.dealCheckSettlement(list, null, financeCheckVO);
            return ResponseData.andaSuccess();
        } else {
            return ResponseData.andaError("请至少选择一条数据进行结算！");
        }
    }

    @ApiOperation(value = "对账单对账")
    @PostMapping("/check/reconciliation")
    @PreAuthorize("@el.check('finance:settlement')")
    @RepeatSubmit(expireSeconds = 3)
    public ResponseData reconciliation(@RequestBody FinanceCheckVO financeCheckVO) {
        FinanceDTO financeDTO = new FinanceDTO();

        // 结算人、运单号不可同时结算
        /*if (checkMultiCondition(financeCheckVO)) {
            return ResponseData.andaError("结算人、运单号不可同时搜索结算");
        }*/
        // -----end---
        if (financeCheckVO.getSettlementIdList() != null && financeCheckVO.getSettlementIdList().size() > 0) {
            List<String> siteAndSettlement = new ArrayList<>();
            List<String> transportList = new ArrayList<>();
            for (String id : financeCheckVO.getSettlementIdList()) {
                if (StringUtils.isBlank(id)) {
                    continue;
                }
                if (id.length() < 10) {
                    transportList.add(id);
                } else if (id.length() > 10) {
                    siteAndSettlement.add(id);
                }
            }
            financeDTO.setSettlementIdList(siteAndSettlement);
            financeDTO.setCheckTransportNoList(transportList);
        } else {
            return ResponseData.andaError("请至少选择一条数据进行结算！");
        }

        financeDTO.setOrderIdList(financeCheckVO.getOrderIdList());
        if (financeDTO.getCheckTransportNoList().size() > 0) {
            for (String transportNo : financeDTO.getCheckTransportNoList()) {
                String transportSettlementId = financeService.getSettlementIdByTransportNo(transportNo);
                if (StringUtils.isBlank(transportSettlementId)) {
                    return ResponseData.andaError("所选运单" + transportNo + "数据存在未处理的结算人，请联系管理员！");
                } else {
                    financeDTO.getSettlementIdList().add(transportSettlementId);
                }
            }

        }
        List<FinanceDetail> list = financeService.getCheckFinanceDetail(financeDTO);
        //List<PkgFinanceCheck> checkList = financeService.getFinanceCheckList(financeDTO);
        if (list != null && list.size() > 0) {
            // 对账单批量结算
            financeService.dealCheckSettlement2(list, null, financeCheckVO);
            return ResponseData.andaSuccess();
        } else {
            return ResponseData.andaError("请至少选择一条数据进行结算！");
        }
    }

    @ApiOperation(value = "对账单详情结算")
    @PostMapping("/check/reconciliationSettle")
    @PreAuthorize("@el.check('finance:settlement')")
    @RepeatSubmit(expireSeconds = 3)
    public ResponseData reconciliationSettle(@RequestBody FinanceCheckVO financeCheckVO) {
        financeService.settlementFincecheck(financeCheckVO);
        return ResponseData.andaSuccess();

    }


    private boolean checkMultiCondition(FinanceCheckVO financeCheckVO) {
        if (financeCheckVO.getSettlementIdList() != null && financeCheckVO.getSettlementIdList().size() > 0) {
            if (StringUtils.isNotBlank(financeCheckVO.getTransportNo())) {
                return true;
            }
        }
        return false;
    }

    @ApiOperation(value = "对账单导出")
    @GetMapping("/check/download")
    public void exportExcel(FinanceDTO financeDTO, HttpServletResponse response) {
        financeService.exportCheckExcel(financeDTO, response);
    }

    @ApiOperation(value = "对账单记录详情导出")
    @GetMapping("/check/download/{id}")
    public void exportCheckDetail(@PathVariable String id, HttpServletResponse response) {
        financeService.exportCheckDetailExcel(id, response);
    }

    @ApiOperation(value = "对账单对账记录分页列表")
    @GetMapping("/check/page")
    public ResponseData getFinanceCheckListPage(FinanceDTO financeDTO) {
        // 排序
        if (StringUtils.isBlank(financeDTO.getColumn())) {
            financeDTO.setColumn("id");
        }
        return financeService.getFinanceCheckListPage(PageFactory.defaultPage(), financeDTO);
    }

    @ApiOperation(value = "对账单结算记录详情")
    @GetMapping("/check/detail/{id}")
    public ResponseData getFinanceCheckDetail(@PathVariable String id) {
        FinanceCheck financeCheck = financeService.getFinanceCheckDetail(id);
        return ResponseData.andaSuccess(ReturnCode.RETURN_SUCCESS.code, financeCheck);
    }

    @ApiOperation(value = "结算记录")
    @GetMapping("/settlement/record")
    public ResponseData<List<PkgFinanceSettlement>> getSettlementRecord(SettlementVO settlementVO) {
        PageResult<PkgFinanceSettlement> list = financeService.getFinanceSettlementList(new Page(1,5000), settlementVO);
        return ResponseData.andaSuccess(list.getRows());
    }

    @ApiOperation(value = "结算记录")
    @GetMapping("/settlement/recordPhone")
    public ResponseData<List<PkgFinanceSettlement>> getSettlementRecordPhone(SettlementVO settlementVO) {
        PageResult<PkgFinanceSettlement> list = financeService.getFinanceSettlementList(PageFactory.defaultPage(), settlementVO);
        return ResponseData.andaSuccess(list);
    }

    @ApiOperation(value = "结算修改")
    @PutMapping("/settlement")
    @BusinessLog(title = "结算修改", opType = LogAnnotionOpTypeEnum.UPDATE)
    public ResponseData updateFinanceSettlement(@RequestBody FinanceSettlement financeSettlement) {
        StringBuilder errorMsg = new StringBuilder();
        if (!financeService.checkFinanceSettlementUpdate(financeSettlement, errorMsg)) {
            return ResponseData.andaError(errorMsg.toString());
        }
        financeService.updateFinanceSettlement(financeSettlement);
        return ResponseData.andaSuccess();
    }

    @ApiOperation(value = "对账单撤销")
    @PutMapping("/check/repeal/{id}")
    @RepeatSubmit(expireSeconds = 3)
    public ResponseData financeCheckRepeal(@PathVariable("id") Long id, @RequestBody List<Long> ids) {
        if (ids.isEmpty()) {
            return ResponseData.error("请选择要撤销的数据");
        }
        financeService.repealFinanceCheck(id, ids);
        return ResponseData.andaSuccess();
    }

    @ApiOperation(value = "结算撤销")
    @PutMapping("/settlement/repeal/{id}")
    @RepeatSubmit(expireSeconds = 3)
    @BusinessLog(title = "结算撤销", opType = LogAnnotionOpTypeEnum.UPDATE)
    public ResponseData financeSettlementRepeal(@PathVariable Long id) {
        StringBuilder errorMsg = new StringBuilder();
        if (!financeService.checkRepealFinanceSettlement(id, errorMsg)) {
            return ResponseData.andaError(errorMsg.toString());
        }
        financeService.repealFinanceSettlement(id);
        return ResponseData.andaSuccess();
    }

    @ApiOperation(value = "应收导出")
    @GetMapping("/collection/download")
    public void collectionExport(FinanceDTO financeDTO, HttpServletResponse response) {
        // 排序
        if (StringUtils.isBlank(financeDTO.getColumn())) {
            financeDTO.setColumn("f.create_time");
        }

        financeService.exportCollectionExcel(financeDTO, response);
    }

    @ApiOperation(value = "应付导出")
    @GetMapping("/payment/download")
    public void paymentExport(FinanceDTO financeDTO, HttpServletResponse response) {
        // 排序
        if (StringUtils.isBlank(financeDTO.getColumn())) {
            financeDTO.setColumn("f.create_time");
        }

        financeService.exportPaymentExcel(financeDTO, response);
    }

    @ApiOperation(value = "毛利表导出")
    @GetMapping("/gross/download")
    public void grossExport(FinanceDTO financeDTO, HttpServletResponse response) {
        // 排序
        if (StringUtils.isBlank(financeDTO.getColumn())) {
            financeDTO.setColumn("os.create_time");
        }

        financeService.exportGross(financeDTO, response);
    }

}
